/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
/*
 * ChartInternalFrame.java
 *
 * Created on 01.12.2009, 18:54:04
 */
package GUI.iFrames;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetDragEvent;
import java.awt.dnd.DropTargetDropEvent;
import java.awt.dnd.DropTargetEvent;
import java.awt.dnd.DropTargetListener;
import java.awt.event.MouseEvent;
import java.io.File;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.swing.JColorChooser;
import javax.swing.JFileChooser;
import javax.swing.JPopupMenu;

import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartMouseEvent;
import org.jfree.chart.ChartMouseListener;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.ChartRenderingInfo;
import org.jfree.chart.ChartUtilities;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.AxisLocation;
import org.jfree.chart.axis.CategoryAxis;
import org.jfree.chart.axis.CategoryLabelPositions;
import org.jfree.chart.axis.DateAxis;
import org.jfree.chart.axis.DateTickMarkPosition;
import org.jfree.chart.axis.DateTickUnit;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.entity.CategoryItemEntity;
import org.jfree.chart.entity.ChartEntity;
import org.jfree.chart.entity.LegendItemEntity;
import org.jfree.chart.entity.XYItemEntity;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.DatasetRenderingOrder;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.category.BarPainter;
import org.jfree.chart.renderer.category.BoxAndWhiskerRenderer;
import org.jfree.chart.renderer.category.LineAndShapeRenderer;
import org.jfree.chart.renderer.category.StackedBarRenderer;
import org.jfree.chart.renderer.category.StackedBarRenderer3D;
import org.jfree.chart.renderer.category.StandardBarPainter;
import org.jfree.chart.renderer.xy.StandardXYBarPainter;
import org.jfree.chart.renderer.xy.XYBarPainter;
import org.jfree.chart.renderer.xy.XYBarRenderer;
import org.jfree.data.DefaultKeyedValues;
import org.jfree.data.category.CategoryDataset;
import org.jfree.data.category.DefaultCategoryDataset;
import org.jfree.data.general.DatasetUtilities;
import org.jfree.data.statistics.DefaultBoxAndWhiskerCategoryDataset;
import org.jfree.data.time.Day;
import org.jfree.data.time.TimeSeries;
import org.jfree.data.time.TimeSeriesCollection;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;

import toolz.StaticExchange;
import DATA.iDataSet;
import DATA.iDataSetParts.Peak;
import DATA.iDataSetParts.Peaklist;
import DATA.iDataSetParts.SubstanceInfo;
import GUI.BaseFrame;
import GUI.ChartTools.legendItemEditorPopup;
import GUI.iFrames.DataSourceComponents.DataSourcesInternalFrame;

/**
 * 
 * @author Bunkowski
 */
public class ChartInternalFrame extends javax.swing.JInternalFrame implements DropTargetListener, ChartMouseListener {

	public static final long serialVersionUID = 1L;

	public DropTarget dropTarget = new DropTarget(this, DnDConstants.ACTION_COPY_OR_MOVE, this, true, null);
	private Vector<String> classLabels, xAchsisLabels;
	private Vector<Double> numericXAchsis;
	private Vector<Vector<Double>> dataLines = new Vector<Vector<Double>>();
	private String chartTitle = "Chart", xAxisLabel = "", yAxisLabel = "intensity";
	private DefaultCategoryDataset barDataset = new DefaultCategoryDataset();
	public XYSeriesCollection lineDataset = new XYSeriesCollection();
	private DefaultBoxAndWhiskerCategoryDataset boxDataset = new DefaultBoxAndWhiskerCategoryDataset();
	PlotOrientation plotorientation = PlotOrientation.VERTICAL;
	private boolean livechart = false;
	private JFreeChart chart;
	private ChartPanel chartPanel;
	private boolean timeseries = false;
	public DataSourcesInternalFrame dsif = null;
	public boolean showLegend = true;
	private Font defaultFont, axisFont;

	/** Creates new form ChartInternalFrame */
	public ChartInternalFrame() {
		initComponents();
	}

	public ChartInternalFrame(String chartTitle, Vector<Double> dataLine, Vector<String> classLabels,
			Vector<String> xAchsisLabels) {
		this.chartTitle = chartTitle;
		this.classLabels = classLabels;
		this.xAchsisLabels = xAchsisLabels;
		initComponents();
		dataLines.add(dataLine);
		if (StaticExchange.xAxsisLabels != null) {
			xAchsisLabels = StaticExchange.xAxsisLabels;
			StaticExchange.xAxsisLabels = null;
		}
		if (StaticExchange.classes != null) {
			classLabels = StaticExchange.classes;
			StaticExchange.classes = null;
		}

		if (!StaticExchange.content.equals("")) {
			chartTitle = (StaticExchange.content);
			StaticExchange.content = "";
		}

		if (lineButton.isSelected()) {
			System.out.println("linechart");
			showAsLineChart();
		}
		if (barButton.isSelected()) {
			System.out.println("barchart");
			showAsBarChart();
		}
		if (boxButton.isSelected()) {
			showAsBoxChart();
		}
		getFonts();
	}

	private void getFonts() {
		defaultFont = chart.getTitle().getFont();
		try {
			axisFont = chart.getXYPlot().getDomainAxis().getLabelFont();
		} catch (Exception ex) {
		}
		try {
			axisFont = chart.getCategoryPlot().getDomainAxis().getLabelFont();
		} catch (Exception ex) {
		}
	}

	public void showAsXYTimeBarChart() {
		timeseries = true;
		TimeSeries ts = new TimeSeries("");
		TimeSeriesCollection timedata = new TimeSeriesCollection(ts);

		HashMap<Day, Integer> divider = new HashMap<Day, Integer>();

		for (int i = 0; i < xAchsisLabels.size(); i++) {
			String s = xAchsisLabels.get(i);
			int year = Integer.parseInt(s.substring(0, 2)) + 2000;
			int month = Integer.parseInt(s.substring(2, 4));
			int day = Integer.parseInt(s.substring(4, 6));
			int hrs = Integer.parseInt(s.substring(6, 8));
			int min = Integer.parseInt(s.substring(8, 10));

			Day d = new Day(day, month, year);
			if (ts.getDataItem(d) == null) {
				ts.add(d, dataLines.get(0).get(i));
			} else {
				double value = ts.getDataItem(d).getValue().doubleValue() + dataLines.get(0).get(i);
				ts.update(d, value);
				int num;
				if (divider.containsKey(d)) {
					num = divider.get(d) + 1;
				} else {
					num = 2;
				}
				divider.put(d, num);
			}

		}
		for (Day d : divider.keySet()) {
			double value = ts.getDataItem(d).getValue().doubleValue();
			ts.update(d, value / divider.get(d));
			// System.out.println("dividing entires from " + d.toString() + " / " + divider.get(d));
		}

		chart = ChartFactory.createXYBarChart(chartTitle, // Title
				xAxisLabel, // x-axis Label
				true, yAxisLabel, // y-axis Label
				timedata, plotorientation, false, false, false);

		XYPlot plot = (XYPlot) chart.getPlot();
		XYBarRenderer renderer = new XYBarRenderer();
		XYBarPainter bp = new StandardXYBarPainter();
		renderer.setBarPainter(bp);
		renderer.setPaint(Color.blue);
		renderer.setShadowVisible(false);
		renderer.setDrawBarOutline(false);

		plot.setRenderer(renderer);

		DateAxis daxis = new DateAxis();
		DateFormat formatter = new SimpleDateFormat("MMM-yyyy");
		DateTickUnit unit = new DateTickUnit(DateTickUnit.MONTH, 1, formatter);

		daxis.setTickUnit(unit);
		daxis.setTickMarkPosition(DateTickMarkPosition.START);
		plot.setDomainAxis(daxis);

		plot.getDomainAxis().setLowerMargin(0);
		plot.getDomainAxis().setUpperMargin(0);

		center.removeAll();
		chartPanel = new ChartPanel(chart);
		center.add(chartPanel);
		chartPanel.addChartMouseListener(this);
		resizeChartTo(StaticExchange.chartResolution);
	}

	public ChartInternalFrame(Vector<Double> dataLine) {
		initComponents();
		dataLines.add(dataLine);
		if (StaticExchange.xAxsisLabels != null) {
			xAchsisLabels = StaticExchange.xAxsisLabels;
			StaticExchange.xAxsisLabels = null;
		}
		if (StaticExchange.classes != null) {
			classLabels = StaticExchange.classes;
			StaticExchange.classes = null;
		}

		if (!StaticExchange.content.equals("")) {
			chartTitle = (StaticExchange.content);
			StaticExchange.content = "";
		}

		if (lineButton.isSelected()) {
			System.out.println("linechart");
			showAsLineChart();
		}
		if (barButton.isSelected()) {
			System.out.println("barchart");
			showAsBarChart();
		}
		if (boxButton.isSelected()) {
			showAsBoxChart();
		}
		getFonts();
	}

	public void setData(String chartTitle, Vector<Double> dataLine, Vector<String> classLabels,
			Vector<String> xAchsisLabels) {
		this.chartTitle = chartTitle;
		this.dataLines.clear();
		this.dataLines.add(dataLine);
		this.classLabels = classLabels;
		this.xAchsisLabels = xAchsisLabels;
		updateChart();
	}

	public void showLineDatasetAsLineChart() {
		JFreeChart lineChart = ChartFactory.createXYLineChart(chartTitle, // Title
				xAxisLabel, // x-axis Label
				yAxisLabel, // y-axis Label
				lineDataset, // Dataset
				plotorientation, // Plot Orientation
				true, // Show Legend
				false, // Use tooltips
				false // Configure chart to generate URLs?
				);

		center.removeAll();
		chartPanel = new ChartPanel(lineChart);
		center.add(chartPanel);
		chartPanel.addChartMouseListener(this);
	}

	public void showAsLineChart() {

		if (numericXAchsis == null) {
			lineDataset.removeAllSeries();
			for (int i = 0; i < dataLines.size(); i++) {
				XYSeries series = new XYSeries("series");
				for (int j = 0; j < dataLines.get(i).size(); j++) {
					Double d = dataLines.get(i).get(j);
					series.add(j, d);
				}
				System.out.println("adding series");
				lineDataset.addSeries(series);
			}
		} else {
			lineDataset.removeAllSeries();
			for (int i = 0; i < dataLines.size(); i++) {
				XYSeries series = new XYSeries("series");
				for (int j = 0; j < dataLines.get(i).size(); j++) {
					Double d = dataLines.get(i).get(j);
					series.add(numericXAchsis.get(j), d);
				}
				System.out.println("adding series");
				lineDataset.addSeries(series);
			}
		}

		JFreeChart lineChart = ChartFactory.createXYLineChart(chartTitle, // Title
				xAxisLabel, // x-axis Label
				yAxisLabel, // y-axis Label
				lineDataset, // Dataset
				plotorientation, // Plot Orientation
				showLegend, // Show Legend
				false, // Use tooltips
				false // Configure chart to generate URLs?
				);

		chart = lineChart;
		center.removeAll();
		chartPanel = new ChartPanel(lineChart);
		center.add(chartPanel);
		chartPanel.addChartMouseListener(this);

	}

	private void buildBarChartDataset() {
		barDataset.clear();
		for (int j = 0; j < dataLines.get(0).size(); j++) {
			Double d = dataLines.get(0).get(j);
			String klass = "";
			if (classLabels != null) {
				klass = classLabels.get(j) + "";
			}
			String xlabel = j + "";
			if (xAchsisLabels != null) {
				xlabel = xAchsisLabels.get(j) + " (" + j + ")";
			}
			barDataset.addValue(d, klass, xlabel);
		}

	}

	private void showAsBarChart() {
		if (!livechart) {
			buildBarChartDataset();
		}
		chart = ChartFactory.createBarChart3D(chartTitle, // Title
				xAxisLabel, // x-axis Label
				yAxisLabel, // y-axis Label
				barDataset, plotorientation, true, false, false);

		CategoryPlot cp = chart.getCategoryPlot();
		StackedBarRenderer sbr = new StackedBarRenderer();
		BarPainter bp = new StandardBarPainter();
		sbr.setDrawBarOutline(true);
		sbr.setBarPainter(bp);
		sbr.setShadowVisible(false);
		cp.setRenderer(sbr);
		CategoryAxis ca = cp.getDomainAxis();
		if (cp.getOrientation() == PlotOrientation.VERTICAL) {
			ca.setCategoryLabelPositions(CategoryLabelPositions.UP_90);
		}
		ca.setLowerMargin(0);
		ca.setUpperMargin(0);
		ca.setCategoryMargin(0);

		/*
		 * BarRenderer br = (BarRenderer)cp.getRenderer(); br.setItemMargin(-1);
		 */

		center.removeAll();
		chartPanel = new ChartPanel(chart);

		// chartpanel.getPopupMenu();

		// chartpanel.setDefaultDirectoryForSaveAs(new File(chartTitle+".png"));
		center.add(chartPanel);
		chartPanel.addChartMouseListener(this);
		resizeChartTo(StaticExchange.chartResolution);
	}

	public void chartMouseClicked(ChartMouseEvent arg0) {

		MouseEvent trigger = arg0.getTrigger();
		System.out.println(trigger.getButton());

		ChartEntity ce = arg0.getEntity();

		if (ce instanceof LegendItemEntity) {
			LegendItemEntity l = (LegendItemEntity) ce;
			l.getSeriesKey();
			XYSeriesCollection col = ((XYSeriesCollection) lineDataset);
			XYSeries s = col.getSeries(l.getSeriesKey());
			JPopupMenu pop = new legendItemEditorPopup(col, s);
			pop.show(chartPanel, arg0.getTrigger().getX(), arg0.getTrigger().getY());
		}

		if (ce instanceof CategoryItemEntity) {
			CategoryItemEntity ci = (CategoryItemEntity) ce;
			Color c = JColorChooser.showDialog(this, "Choose a color", null);
			int catnr = barDataset.getRowIndex(ci.getRowKey());
			chart.getCategoryPlot().getRenderer().setSeriesPaint(catnr, c);
		}

		if (ce instanceof XYItemEntity) {
			System.out.println(((XYItemEntity) ce).getItem());
			if (dsif != null) {
				dsif.table.changeSelection(((XYItemEntity) ce).getItem(), 0, false, false);
				for (String s : dsif.getColumnAt(1)) {
					// gfds
				}
			}
		}
	}

	public void chartMouseMoved(ChartMouseEvent arg0) {
	}

	private void buildBoxDataset() {

		ArrayList<String> categories = new ArrayList<String>();

		if (classLabels == null) {
			classLabels = new Vector<String>();
			for (double d : dataLines.get(0)) {
				classLabels.add("all");
			}
		}

		for (String s : classLabels) {
			if (!categories.contains(s)) {
				categories.add(s);
			}
		}

		for (String category : categories) {
			ArrayList<Double> values = new ArrayList<Double>();
			for (int i = 0; i < classLabels.size(); i++) {
				String classlabel = classLabels.elementAt(i);
				if (classlabel.equals(category)) {
					values.add(dataLines.get(0).get(i));
				}
			}
			boxDataset.add(values, "Boxplot", category);
			// boxDataset.add(values, category,"" );

			// System.out.println(
			// category
			// + " Min RV: "
			// + boxDataset.getMinRegularValue("Boxplot", category)
			// + " Max RV: "
			// + boxDataset.getMaxRegularValue("Boxplot", category));
		}

	}

	public void showAsBoxChart() {

		if (!livechart) {
			buildBoxDataset();
		}

		final CategoryAxis xAxis = new CategoryAxis("class");
		final NumberAxis yAxis = new NumberAxis("intensity");
		yAxis.setAutoRangeIncludesZero(false);
		final BoxAndWhiskerRenderer boxAndWhiskerRenderer = new BoxAndWhiskerRenderer();
		// renderer.
		boxAndWhiskerRenderer.setBaseItemLabelGenerator(null);
		boxAndWhiskerRenderer.setFillBox(false);
		// renderer.setToolTipGenerator(new BoxAndWhiskerToolTipGenerator());

		final CategoryPlot plot = new CategoryPlot(boxDataset, xAxis, yAxis, boxAndWhiskerRenderer);

		plot.setOrientation(plotorientation);

		chart = new JFreeChart(chartTitle, new Font("SansSerif", Font.BOLD, 14), plot, false);

		center.removeAll();
		final ChartPanel chartPanel = new ChartPanel(chart);
		center.add(chartPanel);

		plot.setRangeAxisLocation(AxisLocation.BOTTOM_OR_LEFT);

		// colors start
		// CategoryAxis ca = plot.getDomainAxis();
		// ca.setCategoryMargin(-1);
		// colors end

		try {
			chart.getTitle().setFont(defaultFont);
		} catch (Exception ex) {
		}
		try {
			chart.getXYPlot().getDomainAxis().setLabelFont(axisFont);
			chart.getXYPlot().getRangeAxis().setLabelFont(axisFont);
		} catch (Exception ex) {
		}
		try {
			chart.getCategoryPlot().getDomainAxis().setLabelFont(axisFont);
			chart.getCategoryPlot().getRangeAxis().setLabelFont(axisFont);
		} catch (Exception ex) {
		}

	}

	// for LiCh
	public void createChart(DefaultCategoryDataset dataset) {
		livechart = true;
		chartTitle = "IPHEx live chart";
		showAsBarChart();
	}

	public void setDatatset(DefaultCategoryDataset dataset) {
		this.barDataset = dataset;
	}

	public void updateLiveChart(DataSourcesInternalFrame dataSourcesInternalFrame, SubstanceInfo liveSubstance) {
		Vector<String> ids = dataSourcesInternalFrame.getMeasurementIds();
		int labelIndex = dataSourcesInternalFrame.selectedLabel;
		int classIndex = dataSourcesInternalFrame.selectedClasses;
		iDataSet idataset = dataSourcesInternalFrame.idataset;

		if (barButton.isSelected()) {
			barDataset.clear();

			for (int j = 0; j < ids.size(); j++) {
				Double d = 0.0;
				String id = ids.get(j);
				if (idataset.peaklists.containsKey(id)) {
					Peaklist pl = idataset.peaklists.get(id);
					Peak peak = liveSubstance.getBestHit(pl.getPeaks(), "dt");

					// reference subtraction
					if (idataset.autoSubtractRL == true) {
						Peaklist rlpl = idataset.RLpeaklists.get(id);
						Peak rlpeak = liveSubstance.getBestHit(rlpl.getPeaks(), "dt");
						if (rlpeak != null) {
							d -= rlpeak.intensity;
						}
					}

					if (peak != null) {
						d += peak.intensity;
					}
				}

				String klass = "";
				if (classIndex != -1) {
					klass = dataSourcesInternalFrame.table.getValueAt(j, classIndex) + "";
				}
				String xlabel = j + "";
				if (labelIndex != -1) {
					xlabel = dataSourcesInternalFrame.table.getValueAt(j, labelIndex) + " (" + j + ")";
				}
				barDataset.addValue(d, klass, xlabel);
			}

		} // LIVE BOXCHARTS
		else if (boxButton.isSelected()) {
			boxDataset.clear();

			ArrayList<String> categories = new ArrayList<String>();

			String klass = "";
			for (int j = 0; j < ids.size(); j++) {
				klass = dataSourcesInternalFrame.table.getValueAt(j, classIndex) + "";
				if (!categories.contains(klass)) {
					categories.add(klass);
				}
			}

			for (String category : categories) {
				ArrayList<Double> values = new ArrayList<Double>();
				for (int i = 0; i < ids.size(); i++) {
					String classlabel = dataSourcesInternalFrame.table.getValueAt(i, classIndex) + "";
					Double d = 0.0;
					String id = ids.get(i);
					if (idataset.peaklists.containsKey(id)) {
						Peaklist pl = idataset.peaklists.get(id);
						Peak peak = liveSubstance.getBestHit(pl.getPeaks(), "dt");
						if (peak != null) {
							d = peak.intensity;
						}
						if (classlabel.equals(category)) {
							values.add(d);
						}
					}

				}
				boxDataset.add(values, "Boxplot", category);
			}
		}
	}

	private void updateChart() {

		if (lineButton.isSelected()) {
			showAsLineChart();
		}
		if (barButton.isSelected()) {
			if (timeseries) {
				showAsXYTimeBarChart();
			} else {
				showAsBarChart();
			}
		}
		if (boxButton.isSelected()) {
			showAsBoxChart();
		}
		validate();
		getFonts();
	}

	private void addInformationFromDrop(String drop) {
		String[] dropSequenceArray = drop.split("\n");
		Vector<String> dropSequenceVector = new Vector<String>();
		for (String s : dropSequenceArray) {
			dropSequenceVector.add(s);
		}

		// check if the dropsize is equal to number of datapoints
		if (dropSequenceArray.length == dataLines.get(0).size()) {

			// if no elemets occure twice its an xlabel
			if (!hasElementsTwice(dropSequenceVector)) {
				System.out.println("x-axis labeling drop registred");
				xAchsisLabels = new Vector<String>(dropSequenceVector);

				if (!StaticExchange.content.equals("")) {
					xAxisLabel = StaticExchange.content;
					StaticExchange.content = "";
				}
			} // else it can be a class assignment drop
			else {
				System.out.println("class assignment drop detected");
				classLabels = new Vector<String>(dropSequenceVector);
			}
		}
		updateChart();
	}

	private boolean hasElementsTwice(Vector<String> v) {
		for (int i = 0; i < v.size(); i++) {
			for (int j = i + 1; j < v.size(); j++) {
				if (v.get(i).equals(v.get(j))) {
					return true;
				}
			}
		}
		return false;
	}

	/**
	 * This method is called from within the constructor to initialize the form. WARNING: Do NOT modify this code. The
	 * content of this method is always regenerated by the Form Editor.
	 */
	private void initComponents() {

		buttonGroup1 = new javax.swing.ButtonGroup();
		buttonGroup2 = new javax.swing.ButtonGroup();
		center = new javax.swing.JPanel();
		lineButton = new javax.swing.JToggleButton();
		barButton = new javax.swing.JToggleButton();
		jLabel1 = new javax.swing.JLabel();
		boxButton = new javax.swing.JToggleButton();
		jLabel2 = new javax.swing.JLabel();
		hButton = new javax.swing.JToggleButton();
		vButton = new javax.swing.JToggleButton();
		saveButton = new javax.swing.JButton();
		resField = new javax.swing.JTextField();
		jLabel3 = new javax.swing.JLabel();
		getButton = new javax.swing.JButton();
		setButton = new javax.swing.JButton();
		scoreButton = new javax.swing.JButton();

		setClosable(true);
		setIconifiable(true);
		setMaximizable(true);
		setResizable(true);
		setTitle("Chart viewer");
		addInternalFrameListener(new javax.swing.event.InternalFrameListener() {
			public void internalFrameActivated(javax.swing.event.InternalFrameEvent evt) {
			}

			public void internalFrameClosed(javax.swing.event.InternalFrameEvent evt) {
			}

			public void internalFrameClosing(javax.swing.event.InternalFrameEvent evt) {
				formInternalFrameClosing(evt);
			}

			public void internalFrameDeactivated(javax.swing.event.InternalFrameEvent evt) {
			}

			public void internalFrameDeiconified(javax.swing.event.InternalFrameEvent evt) {
			}

			public void internalFrameIconified(javax.swing.event.InternalFrameEvent evt) {
			}

			public void internalFrameOpened(javax.swing.event.InternalFrameEvent evt) {
			}
		});

		center.setLayout(new javax.swing.BoxLayout(center, javax.swing.BoxLayout.PAGE_AXIS));

		buttonGroup1.add(lineButton);
		lineButton.setText("Line");
		lineButton.setMargin(new java.awt.Insets(2, 5, 2, 5));
		lineButton.addActionListener(new java.awt.event.ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent evt) {
				lineButtonActionPerformed(evt);
			}
		});

		buttonGroup1.add(barButton);
		barButton.setSelected(true);
		barButton.setText("Bar");
		barButton.setMargin(new java.awt.Insets(2, 5, 2, 5));
		barButton.addActionListener(new java.awt.event.ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent evt) {
				barButtonActionPerformed(evt);
			}
		});

		jLabel1.setText("Chart type:");

		buttonGroup1.add(boxButton);
		boxButton.setText("Box");
		boxButton.setMargin(new java.awt.Insets(2, 5, 2, 5));
		boxButton.addActionListener(new java.awt.event.ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent evt) {
				boxButtonActionPerformed(evt);
			}
		});

		jLabel2.setText("Orientation:");

		buttonGroup2.add(hButton);
		hButton.setText("H");
		hButton.setMargin(new java.awt.Insets(2, 5, 2, 5));
		hButton.addActionListener(new java.awt.event.ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent evt) {
				hButtonActionPerformed(evt);
			}
		});

		buttonGroup2.add(vButton);
		vButton.setText("V");
		vButton.setMargin(new java.awt.Insets(2, 5, 2, 5));
		vButton.addActionListener(new java.awt.event.ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent evt) {
				vButtonActionPerformed(evt);
			}
		});

		saveButton.setText("save");
		saveButton.setMargin(new java.awt.Insets(2, 5, 2, 5));
		saveButton.addActionListener(new java.awt.event.ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent evt) {
				saveButtonActionPerformed(evt);
			}
		});

		jLabel3.setText("Res:");

		getButton.setText("get");
		getButton.setMargin(new java.awt.Insets(2, 2, 2, 2));
		getButton.addActionListener(new java.awt.event.ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent evt) {
				getButtonActionPerformed(evt);
			}
		});

		setButton.setText("set");
		setButton.setMargin(new java.awt.Insets(2, 2, 2, 2));
		setButton.addActionListener(new java.awt.event.ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent evt) {
				setButtonActionPerformed(evt);
			}
		});

		scoreButton.setText("!");
		scoreButton.setMargin(new java.awt.Insets(2, 2, 2, 2));
		scoreButton.addActionListener(new java.awt.event.ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent evt) {
				scoreButtonActionPerformed(evt);
			}
		});

		javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
		getContentPane().setLayout(layout);
		layout.setHorizontalGroup(layout
				.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
				.addGroup(
						layout.createSequentialGroup()
								.addContainerGap()
								.addComponent(jLabel1)
								.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
								.addComponent(barButton)
								.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
								.addComponent(boxButton)
								.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
								.addComponent(lineButton)
								.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
								.addComponent(jLabel2)
								.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
								.addComponent(hButton)
								.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
								.addComponent(vButton)
								.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
								.addComponent(jLabel3)
								.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
								.addComponent(resField, javax.swing.GroupLayout.PREFERRED_SIZE, 65,
										javax.swing.GroupLayout.PREFERRED_SIZE)
								.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
								.addComponent(getButton)
								.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
								.addComponent(setButton)
								.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 66,
										Short.MAX_VALUE).addComponent(scoreButton)
								.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
								.addComponent(saveButton).addContainerGap())
				.addComponent(center, javax.swing.GroupLayout.DEFAULT_SIZE, 580, Short.MAX_VALUE));
		layout.setVerticalGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addGroup(
				layout.createSequentialGroup()
						.addContainerGap()
						.addGroup(
								layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
										.addComponent(barButton)
										.addComponent(lineButton)
										.addComponent(boxButton)
										.addComponent(jLabel2)
										.addComponent(hButton)
										.addComponent(vButton)
										.addComponent(saveButton)
										.addComponent(jLabel3)
										.addComponent(resField, javax.swing.GroupLayout.PREFERRED_SIZE,
												javax.swing.GroupLayout.DEFAULT_SIZE,
												javax.swing.GroupLayout.PREFERRED_SIZE).addComponent(getButton)
										.addComponent(setButton).addComponent(jLabel1).addComponent(scoreButton))
						.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
						.addComponent(center, javax.swing.GroupLayout.DEFAULT_SIZE, 307, Short.MAX_VALUE)));

		pack();
	}// </editor-fold>//GEN-END:initComponents

	private void lineButtonActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_lineButtonActionPerformed
		updateChart();
	}// GEN-LAST:event_lineButtonActionPerformed

	private void barButtonActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_barButtonActionPerformed
		updateChart();
	}// GEN-LAST:event_barButtonActionPerformed

	private void boxButtonActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_boxButtonActionPerformed
		updateChart();
	}// GEN-LAST:event_boxButtonActionPerformed

	private void hButtonActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_hButtonActionPerformed
		plotorientation = PlotOrientation.HORIZONTAL;
		try {
			((CategoryPlot) chart.getPlot()).setOrientation(plotorientation);
			((CategoryPlot) chart.getPlot()).getDomainAxis().setCategoryLabelPositions(CategoryLabelPositions.STANDARD);
		} catch (Exception e) {
		}
		try {
			((XYPlot) chart.getPlot()).setOrientation(plotorientation);
		} catch (Exception e) {
		}

	}// GEN-LAST:event_hButtonActionPerformed

	private void vButtonActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_vButtonActionPerformed
		plotorientation = PlotOrientation.VERTICAL;
		try {
			((CategoryPlot) chart.getPlot()).setOrientation(plotorientation);
			((CategoryPlot) chart.getPlot()).getDomainAxis().setCategoryLabelPositions(CategoryLabelPositions.UP_90);
		} catch (Exception e) {
		}
		try {
			((XYPlot) chart.getPlot()).setOrientation(plotorientation);
		} catch (Exception e) {
		}
	}// GEN-LAST:event_vButtonActionPerformed

	private void saveButtonActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_saveButtonActionPerformed
		JFileChooser chooser = new JFileChooser(BaseFrame.getSelectedFileTreeFile());
		chooser.setSelectedFile(new File(chartTitle + ".png"));
		chooser.setDialogType(JFileChooser.SAVE_DIALOG);
		int returnVal = chooser.showOpenDialog(null);
		if (returnVal == JFileChooser.APPROVE_OPTION) {
			try {
				java.io.File file = chooser.getSelectedFile();
				if (!file.toString().endsWith(".png")) {
					file = new java.io.File(file.getPath() + ".png");
				}
				ChartRenderingInfo info = new ChartRenderingInfo();
				ChartUtilities.saveChartAsPNG(file, chart, 1400, 1050, info);
			} catch (IOException ex) {
				Logger.getLogger(ChartInternalFrame.class.getName()).log(Level.SEVERE, null, ex);
			}
		}
	}

	public void saveToFolder(String folder) {
		if (chartTitle.contains("\\")) {
			chartTitle = chartTitle.replace("\\", "-");
		}
		if (chartTitle.contains(".")) {
			chartTitle = chartTitle.replace(".", "_");
		}
		if (chartTitle.contains("?")) {
			chartTitle = chartTitle.replace("?", "#");
		}

		String charttype = "";
		if (chart.getCategoryPlot().getRenderer() instanceof StackedBarRenderer3D) {
			charttype = "_BarChart";
		}
		if (chart.getCategoryPlot().getRenderer() instanceof BoxAndWhiskerRenderer) {
			charttype = "_BoxPlot";
		}

		File file = new File(folder + "\\" + chartTitle.trim() + charttype + ".png");
		try {

			ChartRenderingInfo info = new ChartRenderingInfo();
			ChartUtilities.saveChartAsPNG(file, chart, 1400, 1050, info);
		} catch (IOException ex) {
			Logger.getLogger(ChartInternalFrame.class.getName()).log(Level.SEVERE, null, ex);
		}
	}// GEN-LAST:event_saveButtonActionPerformed

	public void disableChartTypeButtons() {
		barButton.setEnabled(false);
		boxButton.setEnabled(false);
		lineButton.setEnabled(false);
		hButton.setEnabled(false);
		vButton.setEnabled(false);
	}

	private void formInternalFrameClosing(javax.swing.event.InternalFrameEvent evt) {// GEN-FIRST:event_formInternalFrameClosing
	}// GEN-LAST:event_formInternalFrameClosing

	private void getButtonActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_getButtonActionPerformed
		resField.setText(chartPanel.getWidth() + "x" + chartPanel.getHeight());
	}// GEN-LAST:event_getButtonActionPerformed

	private void setButtonActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_setButtonActionPerformed
		resizeChartTo(resField.getText());
		resizeChartTo(resField.getText());
		StaticExchange.chartResolution = resField.getText();
	}// GEN-LAST:event_setButtonActionPerformed

	private void scoreButtonActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_scoreButtonActionPerformed
		Vector<String> classes = new Vector<String>();
		int clms = barDataset.getColumnCount();
		int rows = barDataset.getRowCount();

		// Step1: finding the class names
		for (int c = 0; c < clms; c++) {
			for (int r = 0; r < rows; r++) {
				if (barDataset.getValue(r, c) != null) {
					System.out.print(barDataset.getColumnKey(c) + "\t");
					System.out.print(barDataset.getRowKey(r) + "\t");
					System.out.println(barDataset.getValue(r, c));
					if (!classes.contains((barDataset.getRowKey(r).toString()))) {
						classes.add(barDataset.getRowKey(r).toString());
					}
				}
			}
		}
		if (classes.size() != 2) {
			System.out.println("ERROR can only process 2 classes");
		} else {

			String A = classes.get(0);
			String B = classes.get(1);
			double totalAs = 0;
			double totalBs = 0;

			// Step2: counting class members
			for (int c = 0; c < clms; c++) {
				for (int r = 0; r < rows; r++) {
					if (barDataset.getValue(r, c) != null) {

						if (A.equals((barDataset.getRowKey(r).toString()))) {
							totalAs++;
						} else {
							totalBs++;
						}

					}
				}
			}
			System.out.println(totalAs + " counts of class " + A);
			System.out.println(totalBs + " counts of class " + B);
			double total = totalAs + totalBs;

			int As = 0;
			int Bs = 0;
			XYSeries accuracy = new XYSeries("Separation accuracy");
			final DefaultKeyedValues data = new DefaultKeyedValues();
			for (int c = 0; c < clms; c++) {
				for (int r = 0; r < rows; r++) {
					if (barDataset.getValue(r, c) != null) {
						String thisClass = barDataset.getRowKey(r).toString();
						if (thisClass.equals(A)) {
							As++;
						} else {
							Bs++;
						}
						// double accRelative = (As/(totalAs/total) + (totalBs-Bs)/(totalBs/total));
						double accAbsolute = (As + totalBs - Bs) / total * 100;
						// System.out.println(accRelative);
						// data.addValue(c+"", accRelative);
						// accuracy.add(c, accRelative);
						System.out.println(accAbsolute);
						data.addValue(c + "", accAbsolute);
						accuracy.add(c, accAbsolute);
					}
				}
			}

			final CategoryDataset dataset2 = DatasetUtilities.createCategoryDataset("separation accuracy", data);

			final NumberAxis axis2 = new NumberAxis("[%]");
			axis2.setLabelFont(axisFont);
			CategoryPlot cp = chart.getCategoryPlot();

			axis2.setRange(accuracy.getMinY(), 100);
			final LineAndShapeRenderer renderer2 = new LineAndShapeRenderer();

			cp.setRangeAxis(1, axis2);
			cp.setDataset(1, dataset2);
			cp.setRenderer(1, renderer2);

			cp.mapDatasetToRangeAxis(1, 1);
			renderer2.setSeriesPaint(0, Color.DARK_GRAY);
			cp.setDatasetRenderingOrder(DatasetRenderingOrder.FORWARD);
		}
	}// GEN-LAST:event_scoreButtonActionPerformed

	private void resizeChartTo(String size) {
		if (size != null) {
			String[] values = size.split("x");
			chartPanel.setSize(Integer.parseInt(values[0]), Integer.parseInt(values[1]));
			// chartPanel.setPreferredSize(new Dimension(Integer.parseInt(values[0]), Integer.parseInt(values[1])));
			chartPanel.setMinimumSize(new Dimension(Integer.parseInt(values[0]), Integer.parseInt(values[1])));
			chartPanel.setMaximumSize(new Dimension(Integer.parseInt(values[0]), Integer.parseInt(values[1])));
			pack();
			validate();
			chartPanel.setMinimumSize(new Dimension(0, 0));
			chartPanel.setMaximumSize(new Dimension(9999999, 9999999));

		}
	}

	// Variables declaration - do not modify//GEN-BEGIN:variables
	private javax.swing.JToggleButton barButton;
	private javax.swing.JToggleButton boxButton;
	private javax.swing.ButtonGroup buttonGroup1;
	private javax.swing.ButtonGroup buttonGroup2;
	private javax.swing.JPanel center;
	private javax.swing.JButton getButton;
	private javax.swing.JToggleButton hButton;
	private javax.swing.JLabel jLabel1;
	private javax.swing.JLabel jLabel2;
	private javax.swing.JLabel jLabel3;
	public javax.swing.JToggleButton lineButton;
	private javax.swing.JTextField resField;
	private javax.swing.JButton saveButton;
	private javax.swing.JButton scoreButton;
	private javax.swing.JButton setButton;
	private javax.swing.JToggleButton vButton;

	// End of variables declaration//GEN-END:variables

	public void dragEnter(DropTargetDragEvent dtde) {
	}

	public void dragOver(DropTargetDragEvent dtde) {
	}

	public void dropActionChanged(DropTargetDragEvent dtde) {
	}

	public void dragExit(DropTargetEvent dte) {
	}

	public void drop(DropTargetDropEvent evt) {

		try {
			Transferable t = evt.getTransferable();
			String drop = (String) t.getTransferData(DataFlavor.stringFlavor);
			addInformationFromDrop(drop);
		} catch (UnsupportedFlavorException ex) {
		} catch (IOException ex) {
		}
	}
}
